<?php
namespace app\apijson\query\operators;

class WhereHasOperator
{
    public static function apply($query, $value)
    {
        // 支持多种格式：
        // 1. 简单格式: {"user": {"name": "test"}}
        // 2. 复杂格式: {"user": {"@column": "id,name", "@where": {"status": 1}}}
        // 3. 嵌套格式: {"user": {"posts": {"title": "test"}}}
        // 4. 点结构格式: {"user.mak": {"name": "test"}} 或 {"user": {"mak.name": "test"}}
        
        if (is_array($value)) {
            foreach ($value as $relation => $conditions) {
                self::processWhereHas($query, $relation, $conditions);
            }
        }
    }

    private static function processWhereHas($query, $relation, $conditions)
    {
        // 验证关联名，支持点结构如 user.mak
        if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_.]*$/', $relation)) {
            throw new \app\apijson\core\ApiJsonException('非法关联名: ' . $relation);
        }

        $query->whereHas($relation, function($subQuery) use ($conditions) {
            self::applyConditions($subQuery, $conditions);
        });
    }

    private static function applyConditions($query, $conditions)
    {
        if (!is_array($conditions)) {
            return;
        }

        foreach ($conditions as $key => $value) {
            if ($key[0] === '@') {
                // 处理特殊操作符
                self::applySpecialOperator($query, $key, $value);
            } elseif (is_array($value) && !self::isSimpleArray($value)) {
                // 嵌套关联查询
                self::processWhereHas($query, $key, $value);
            } else {
                // 普通条件，支持点结构如 user.mak
                if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_.*]*$/', $key)) {
                    throw new \app\apijson\core\ApiJsonException('非法字段名: ' . $key);
                }
                $query->where($key, $value);
            }
        }
    }

    private static function applySpecialOperator($query, $key, $value)
    {
        switch ($key) {
            case '@column':
                ColumnOperator::apply($query, $value);
                break;
            case '@order':
                OrderOperator::apply($query, $value);
                break;
            case '@group':
                GroupOperator::applyGroup($query, $value);
                break;
            case '@having':
                GroupOperator::applyHaving($query, $value);
                break;
            case '@between':
                BetweenOperator::apply($query, $value);
                break;
            case '@in':
                InOperator::apply($query, $value);
                break;
            case '@where':
                // 支持额外的where条件，支持点结构如 user.mak
                if (is_array($value)) {
                    foreach ($value as $field => $val) {
                        if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_.*]*$/', $field)) {
                            throw new \app\apijson\core\ApiJsonException('非法字段名: ' . $field);
                        }
                        $query->where($field, $val);
                    }
                }
                break;
            case '@orWhere':
                // 支持orWhere条件，支持点结构如 user.mak
                if (is_array($value)) {
                    $query->where(function($q) use ($value) {
                        foreach ($value as $field => $val) {
                            if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_.*]*$/', $field)) {
                                throw new \app\apijson\core\ApiJsonException('非法字段名: ' . $field);
                            }
                            $q->orWhere($field, $val);
                        }
                    });
                }
                break;
            case '@whereIn':
                // 支持whereIn条件，支持点结构如 user.mak
                if (is_array($value)) {
                    foreach ($value as $field => $values) {
                        if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_.*]*$/', $field)) {
                            throw new \app\apijson\core\ApiJsonException('非法字段名: ' . $field);
                        }
                        if (is_array($values)) {
                            $query->whereIn($field, $values);
                        } elseif (is_string($values)) {
                            $valueArray = array_map('trim', explode(',', $values));
                            $query->whereIn($field, $valueArray);
                        }
                    }
                }
                break;
            case '@whereNull':
                // 支持whereNull条件，支持点结构如 user.mak
                if (is_string($value)) {
                    $fields = array_map('trim', explode(',', $value));
                    foreach ($fields as $field) {
                        if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_.*]*$/', $field)) {
                            throw new \app\apijson\core\ApiJsonException('非法字段名: ' . $field);
                        }
                        $query->whereNull($field);
                    }
                } elseif (is_array($value)) {
                    foreach ($value as $field) {
                        if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_.*]*$/', $field)) {
                            throw new \app\apijson\core\ApiJsonException('非法字段名: ' . $field);
                        }
                        $query->whereNull($field);
                    }
                }
                break;
            case '@whereNotNull':
                // 支持whereNotNull条件，支持点结构如 user.mak
                if (is_string($value)) {
                    $fields = array_map('trim', explode(',', $value));
                    foreach ($fields as $field) {
                        if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_.*]*$/', $field)) {
                            throw new \app\apijson\core\ApiJsonException('非法字段名: ' . $field);
                        }
                        $query->whereNotNull($field);
                    }
                } elseif (is_array($value)) {
                    foreach ($value as $field) {
                        if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_.*]*$/', $field)) {
                            throw new \app\apijson\core\ApiJsonException('非法字段名: ' . $field);
                        }
                        $query->whereNotNull($field);
                    }
                }
                break;
            default:
                // 处理其他操作符（模糊查询、逻辑运算符等）
                if (JsonOperator::apply($query, $key, $value)) {
                    return;
                }
                if (LikeOperator::apply($query, $key, $value)) {
                    return;
                }
                if (LogicOperator::apply($query, $key, $value)) {
                    return;
                }
                break;
        }
    }

    private static function isSimpleArray($array)
    {
        // 判断是否为简单数组（非关联数组）
        return array_keys($array) === range(0, count($array) - 1);
    }
} 